package com.xiaomaoguai.fcp.fcp.controller.redis;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.xiaomaoguai.xxr.dto.req.PublicReqDTO;
import com.github.xiaomaoguai.xxr.properties.ZaProperties;
import com.github.xiaomaoguai.xxr.utils.http.HttpClientUtil;
import com.github.xiaomaoguai.xxr.utils.json.JsonUtils;
import com.github.xiaomaoguai.xxr.utils.security.AES;
import com.github.xiaomaoguai.xxr.utils.security.RSA;
import com.xiaomaoguai.fcp.fcp.dto.ResponseModel;
import com.xiaomaoguai.fcp.fcp.utils.ReqUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * @fileName: DynamicCallController.java
 * @author: WeiHui
 * @date: 2018/9/13 13:41
 * @version: v1.0.0
 * @since JDK 1.8
 */
@Slf4j
@RestController
@RequestMapping("/dynamic")
@Api(value = "动态调用小杏仁，只需要请求实例的参数")
public class DynamicCallController {

	private static final String aesKey = "BF58217B493783BB";

	@Resource
	private ZaProperties zaProperties;

	@Resource
	private RedisTemplate<String, String> redisTemplate;

	@Resource(name = "redisTemplate")
	private HashOperations<String, String, String> hashOperations;

	@PostMapping("/getReqData")
	@ApiOperation(value = "获取之前的请求参数")
	public Object info(String key) {
		Map<String, Map<String, String>> maps = new HashMap<>(10);
		if (StringUtils.isNotBlank(key)) {
			Set<String> keys = redisTemplate.keys(key);
			keys.forEach(k -> {
				DataType dataType = redisTemplate.type(k);
				if (DataType.HASH.equals(dataType)) {
					maps.putIfAbsent(k, new HashMap<>(10));
					Set<String> hashKeys = hashOperations.keys(k);
					hashKeys.forEach(hk -> maps.get(k).put(hk, hashOperations.get(k, hk)));
				}
			});
		}
		return maps;
	}

	@PostMapping("/invoke")
	@ApiOperation(value = "动态调用")
	public ResponseModel<Map<String, Object>> dynamicInvoke(@RequestBody String content) throws Exception {
		ResponseModel<Map<String, Object>> mapResponseModel = new ResponseModel<>();
		Map<String, Object> objectMap = new TreeMap<>();
		mapResponseModel.setData(objectMap);

		log.info("\n===========报文============\n{}", JsonUtils.formatJson(content));
		ObjectNode jsonNode = (ObjectNode) JsonUtils.getObjectMapper().readTree(content);
		String thirdUserNo = jsonNode.get("thirdUserNo").asText();
		String apiName = jsonNode.get("apiName").asText();
		String transName = jsonNode.get("transName").asText();
		String token = ReqUtils.buildToken(thirdUserNo, aesKey);
		jsonNode.put("token", token);
		jsonNode.put("reqDate", FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss").format(new Date()));
		log.info("\n===========请求小杏仁业务报文开始============\n{}", JsonUtils.formatJson(jsonNode.toString()));
		objectMap.put("param", jsonNode.toString());

		PublicReqDTO publicReqDTO = buildPublicReqDTO(jsonNode.toString(), aesKey);
		String reqUrl = ReqUtils.buildReqUrl(zaProperties.getUrl(), apiName, transName);
		String jsonString = JsonUtils.toJsonString(publicReqDTO);
		log.info("\n===========请求小杏仁完整报文开始============\n{}", JsonUtils.formatJson(jsonString));
		String result = HttpClientUtil.doPost(reqUrl, jsonString);
		String respJson = result.substring(1, result.length() - 1).replace("\\u003d\\", "=").replaceAll("\\\\", "");
		log.info("\n===========请求小杏仁结果============\n{}", JsonUtils.formatJson(respJson));
		ResponseModel<Object> responseModel = new ResponseModel<>(respJson);
		ObjectNode resultJsonNode = (ObjectNode) JsonUtils.getObjectMapper().readTree(respJson);
		if (ReqUtils.isSuccess(resultJsonNode.get("respCode").asText())) {
			String respContent = resultJsonNode.get("respContent").toString();
			respContent = respContent.replace("u003d", "=");
			String decryptContent = AES.decryptFromBase64(respContent, aesKey);
			log.info("众安返回报文：\n {}", JsonUtils.formatJson(decryptContent));
			objectMap.put("result", decryptContent);
			responseModel.setData(decryptContent);
			// 请求正常，保存报文，待后续利用
			hashOperations.put(apiName, transName, content);
		}
		return mapResponseModel;
	}

	private PublicReqDTO buildPublicReqDTO(String bizReq, String aesKey) throws Exception {
		PublicReqDTO publicReqDTO = new PublicReqDTO();
		publicReqDTO.setClient(this.zaProperties.getClient());
		publicReqDTO.setChannelID(this.zaProperties.getChannelId());
		String key = RSA.encrypt(aesKey, this.zaProperties.getPublicKey());
		publicReqDTO.setKey(key);
		String reqContent = AES.encryptToBase64(bizReq, aesKey);
		publicReqDTO.setReqContent(reqContent);
		return publicReqDTO;
	}

}
